package org.example.controller;

import lombok.extern.slf4j.Slf4j;
import org.example.commonapi.domain.FormData;
import org.example.commonapi.domain.R;
import org.example.commonapi.dto.onlineCode.CodeDto;
import org.example.commonapi.dto.SpeechAssessmentDTO;
import org.example.commonapi.response.bigmodel.SparkChatListener;
import org.example.commonapi.util.JwtUtil;
import org.example.commonapi.util.oss.OssService;
import org.example.commonapi.vo.CorrectionErrorVO;
import org.example.commonapi.vo.PhotoCalculateVO;
import org.example.commonapi.vo.WordScoreVO;
import org.example.service.AiChatService;
import org.example.service.AiToolService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.CompletableFuture;

/**
 * 存放ai相关功能的Controller
 */

@RestController
@RequestMapping("/aiChat")
@Slf4j
public class AiToolController {

    @Autowired
    private AiToolService aiToolService;

    @Autowired
    private AiChatService aiChatService;

    @Autowired
    private OssService ossService;

    @Autowired
    private JwtUtil jwtUtil;

    /**
     * 机器翻译
     * @param text
     * @param from
     * @param to
     * @return
     */
    @GetMapping("/machineTranslate")
    public R<String> machineTranslate(@RequestParam("text") String text,@RequestParam("from") String from,@RequestParam("to") String to) {
        return aiToolService.machineTranslate(text,from,to);
    }

    /**
     * ai审核视频是否合规
     * @param videoUrl
     * @return
     * @throws IOException
     */
    @GetMapping("/aiCheckVideo")
    public R<String> aiCheckVideo(@RequestParam("videoUrl") String videoUrl) throws Exception {
        return aiToolService.aiCheckVideo(videoUrl);
    }

    /**
     * ai自动对文本进行纠错
     * @param text
     * @return
     */
    @GetMapping("/aiCorrectionError")
    public R<List<CorrectionErrorVO>> aiCorrectionError(@RequestParam("text") String text) throws Exception {
        return aiToolService.aiCorrectError(text);
    }

    /**
     * ai改写文本 level代表改写的等级
     * @param text
     * @param level
     * @return
     * @throws Exception
     */
    @GetMapping("/aiTextRewrite")
    public R<String> aiTextRewrite(@RequestParam("text") String text, @RequestParam("level") String level) throws Exception {
        return aiToolService.aiTextRewrite(text,level);
    }

    /**
     * 需要先调用 aiChatController里面的getBase64Link接口获取图片的base64链接对应的UID 传入UID进行图片转文字
     * @param UID
     * @return
     * @throws Exception
     */
    @GetMapping("/characterRecognition")
    public R<String> characterRecognition(@RequestParam("UID") String UID) throws Exception {
        return aiToolService.characterRecognition(UID);
    }

    /**
     * 将图片转化为电子稿 返回阿里云OSS下载链接
     * @param UID
     * @param type
     * @param encoding 图片后缀
     * @return
     * @throws Exception
     */
    @GetMapping("/pictureDocument")
    public R<String> pictureDocument(@RequestParam("UID") String UID,@RequestParam("type") String type,@RequestParam("encoding") String encoding) throws Exception {
        return aiToolService.pictureDocument(UID,type,encoding);
    }

    /**
     * 公式识别 返回识别出的公式字符串
     * @param UID
     * @return
     * @throws Exception
     */
    @GetMapping("/formulaRecognition")
    public R<String> formulaRecognition(@RequestParam("UID") String UID) throws Exception {
        return aiToolService.formulaRecognition(UID);
    }

    /**
     * 语音识别 返回识别出的文本 参数：音频 题目 题型
     * 这里没有加@RequestBody因为加上后Spring会将传输改为application/json 而前端传输为multipart/form-data 因此会报错
     * @param speechAssessmentDTO
     * @return
     * @throws Exception
     */
    @PostMapping("/speechAssessment")
    public R<List<WordScoreVO>> speechAssessment(SpeechAssessmentDTO speechAssessmentDTO) throws Exception {
        return aiToolService.speechAssessment(speechAssessmentDTO);
    }

    /**
     * 根据题目种类获取随机题目 可以更换成ai
     * @param category
     * @return
     */
    @GetMapping("/getRandomSpeechText")
    public R<String> getRandomSpeechText(@RequestParam("category") String category) {
        System.out.println(category);
        return aiToolService.getRandomSpeechText(category);
    }

    /**
     * 识别图中公式 并判断计算是否正确
     * @param UID
     * @return
     */
    @GetMapping("/photoCalculate")
    public R<List<PhotoCalculateVO>> photoCalculate(@RequestParam("UID") String UID) throws Exception {
        return aiToolService.photoCalculate(UID);
    }

    /**
     * 获取当天该用户调用各个功能的频率
     * @param request
     * @return
     */
    @GetMapping("/getToolFrequency")
    public R<List<Integer>> getToolFrequency(HttpServletRequest request) {
        return aiToolService.getToolFrequency(request);
    }

    /**
     * 更新用户当天调用指定功能的频率
     * @param idx
     * @param request
     * @return
     */
    @PutMapping("/updateToolFrequency")
    public R updateToolFrequency(Integer idx,HttpServletRequest request) {
        return aiToolService.updateToolFrequency(idx,request);
    }

    /**
     * 实时语音识别 返回识别出的文本
     * @param source
     * @return
     * @throws Exception
     */
    @GetMapping(value = "/realTimeASR", produces = {MediaType.TEXT_EVENT_STREAM_VALUE})
    public SseEmitter realTimeASR(@RequestParam String source,HttpServletRequest request) throws Exception {
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        final SseEmitter emitter = aiChatService.getConn(userId);
        CompletableFuture.runAsync(()->{
            try {
                aiToolService.realTimeASR(source,emitter);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        return emitter;
    }

    /**
     * 停止实时语音识别
     * @return
     */
    @GetMapping("/stopRealTimeASR")
    public R stopRealTimeASR() {
        return aiToolService.stopRealTimeASR();
    }

    /**
     * 人脸比对 用于考试时讲用户证件照与摄像头捕捉的人脸进行比对
     * @param formData
     * @param request
     * @return
     * @throws Exception
     */
    @PostMapping("/faceCompare")
    public R<Integer> faceCompare(FormData formData,HttpServletRequest request) throws Exception {
        return aiToolService.faceCompare(formData,request);
    }

    /**
     * ai流式代码分析
     * @param code 要分析的代码
     * @return
     */
    @PostMapping(value = "/analysisCode")
    public SseEmitter analysisCode(@RequestBody CodeDto code,HttpServletRequest request) {
        System.out.println(code.getCode());
        Long userId = jwtUtil.parseJwt(request.getHeader("token")).getId();
        final SseEmitter emitter = aiChatService.getConn(userId);
        CompletableFuture.runAsync(()->{
            StringBuilder answerCache = new StringBuilder();
            SparkChatListener sparkChatListener;
            StringBuilder question = new StringBuilder("这是一段C++代码，逐行分析下这段代码，按照当前行解析，换行，当前行md代码块展示的方式进行解析,最后再给出一些修改意见并给出修改后的代码");
            question.append("\n```cpp\n");
            question.append(code.getCode());
            question.append("\n```");
            try {
                sparkChatListener = aiToolService.analysisCode(question, answerCache);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
            int lastIdx = 0, len = 0;
            try {
                while (!sparkChatListener.getWsCloseFlag()) {
                    if(lastIdx < (len = answerCache.length())){
                        String sendMessage = answerCache.substring(lastIdx, len);
                        // 替换所有回车换行 空格替换为占位符
                        sendMessage = sendMessage.replaceAll(" ","&#32;").replaceAll("\n", "&#92n");
                        System.out.println("发送数据=>" + sendMessage);
                        emitter.send(sendMessage);
                        lastIdx = len;
                    }
                }
                emitter.send("&#92n[DONE]");
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        });
        return emitter;
    }
}
